package cn.ulc.socket.admin.service.order.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.ulc.common.constant.PubDataConstant;
import cn.ulc.common.constant.enums.AvailableStatus;
import cn.ulc.common.exception.PlatformException;
import cn.ulc.common.model.param.PaginationParam;
import cn.ulc.common.util.CalendarUtil;
import cn.ulc.socket.admin.common.BaseService;
import cn.ulc.socket.admin.model.dto.order.OrderListDTO;
import cn.ulc.socket.admin.service.order.OrderServ;
import cn.ulc.socket.common.api.WxPayAPI;
import cn.ulc.store.dao.DepositDao;
import cn.ulc.store.dao.order.OrderDao;
import cn.ulc.store.dao.order.OrderExpressRecordDao;
import cn.ulc.store.dao.staff.StaffDao;
import cn.ulc.store.dao.staff.StaffOrderDao;
import cn.ulc.store.dao.user.MemberDao;
import cn.ulc.store.entity.Company;
import cn.ulc.store.entity.PubData;
import cn.ulc.store.entity.order.Order;
import cn.ulc.store.entity.order.OrderExpressRecord;
import cn.ulc.store.entity.order.OrderItem;
import cn.ulc.store.entity.staff.Staff;
import cn.ulc.store.entity.staff.StaffOrder;
import cn.ulc.store.entity.user.Member;
import lombok.AllArgsConstructor;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service
@AllArgsConstructor
public class OrderServImpl extends BaseService implements OrderServ {
    OrderDao orderDao;
    StaffOrderDao staffOrderDao;
    StaffDao staffDao;
    DepositDao depositDao;
    OrderExpressRecordDao orderExpressRecordDao;
    WxPayAPI wxPayAPI;
    MemberDao memberDao;
    @Override
    public OrderListDTO findListPage(String orderNo, String status, String begin, String end, PaginationParam param) {
        Staff loginUser = getCurrentUser();
        Map<String,Object> condition = new HashMap<>();
        condition.put("orderNo",orderNo);
        condition.put("beginDate",begin);
        condition.put("endDate",end);
        condition.put("companyId",loginUser.getCompanyId());
        condition.put("status",status);
        PageQuery pageQuery = initPageQuery(param);
        pageQuery.setParas(condition);
        orderDao.findListPage(pageQuery);
        return new OrderListDTO(pageQuery.getList(),pageQuery.getTotalRow());
    }
    @Override
    public OrderListDTO findRiderListPage(Long riderId,String orderNo,String begin, String end, PaginationParam param) {
        Map<String,Object> condition = new HashMap<>();
        condition.put("orderNo",orderNo);
        condition.put("beginDate",begin);
        condition.put("endDate",end);
        condition.put("riderId",riderId);
        PageQuery pageQuery = initPageQuery(param);
        pageQuery.setParas(condition);
        orderDao.findRiderListPage(pageQuery);
        return new OrderListDTO(pageQuery.getList(),pageQuery.getTotalRow());
    }

    @Override
    @Transactional
    public Boolean dispatchOrder(String orderNo, Long riderId) {
        riderId = Convert.toLong(riderId,0l);
        if(StrUtil.isBlank(orderNo) || riderId <= 0) return false;
        Order order = orderDao.findByOrderNo(orderNo);
        Staff rider = staffDao.findOne(riderId);
        if(order != null && rider != null){
            if(PubDataConstant.ORDER_PAID.equals(order.getStatus())){
                StaffOrder entity = new StaffOrder();
                setBaseInfo(entity);
                entity.setOrderId(order.getId());
                entity.setOrderNo(order.getOrderNo());
                entity.setStaffId(riderId);
                staffOrderDao.save(entity);

                //同步订单状态
                setBaseInfo(order);
                order.setStatus(PubDataConstant.ORDER_DELIVERED);
                orderDao.save(order);

                //产生物流信息
                OrderExpressRecord record = new OrderExpressRecord();
                setBaseInfo(record);
                record.setOrderId(order.getId());
                record.setOrderNo(order.getOrderNo());
                record.setContact(rider.getName());
                record.setContactPhone(rider.getServiceCall());
                record.setContent("订单分派给骑手:"+rider.getName()+",联系方式:"+rider.getServiceCall());
                orderExpressRecordDao.save(record);
                return true;
            }
        }
        return false;
    }



    @Override
    public Boolean refund(String orderNo) {
        Order order = orderDao.findByOrderNo(orderNo);
        if(order == null) throw new PlatformException("未获取到订单信息");
        Map<String,Object> map = wxPayAPI.wxRefund(order.getOrderNo());
        if(Boolean.valueOf(map.get("success").toString()) == false){
            throw new PlatformException(map.get("msg").toString());
        }
        return true;
    }

    @Override
    public Map<String, Object> findMemberStat(String beginDate, String endDate) {
        Company company = getCurrentCompany();
        Map<String,Object> orders = orderDao.findMemberStat(company.getId(),beginDate,endDate);
        BigDecimal totalAmount = (BigDecimal) orders.get("totalAmount");
        BigDecimal newTotalAmount = (BigDecimal) orders.get("newTotalAmount");
        BigDecimal oldTotalAmount = (BigDecimal) orders.get("oldTotalAmount");
        BigDecimal  totalCount =new BigDecimal((Long) orders.get("totalCount"));
        BigDecimal  newTotalCount =new BigDecimal((Long) orders.get("newTotalCount"));
        BigDecimal  oldTotalCount =new BigDecimal((Long) orders.get("oldTotalCount"));
        BigDecimal  activeCount =new BigDecimal((Long) orders.get("activeCount"));
        BigDecimal newAmountPre = totalAmount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:newTotalAmount.multiply(new BigDecimal("100")).divide(totalAmount,2,RoundingMode.HALF_UP);
        BigDecimal oldAmountPre = totalAmount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO: oldTotalAmount.multiply(new BigDecimal("100")).divide(totalAmount,2,RoundingMode.HALF_UP);
        BigDecimal newCountPre =  totalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:newTotalCount.multiply(new BigDecimal("100")).divide(totalCount,2,RoundingMode.HALF_UP);
        BigDecimal oldCountPre =  totalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:oldTotalCount.multiply(new BigDecimal("100")).divide(totalCount,2,RoundingMode.HALF_UP);
        orders.put("newAmountPre",newAmountPre);  //新会员消费金额比例
        orders.put("oldAmountPre",oldAmountPre);   //老会员消费金额比例
        orders.put("oldCountPre",oldCountPre);   //老会员订单数比例
        orders.put("newCountPre",newCountPre);    //新会员订单数比例
        List<Member> memberList = memberDao.findList(company.getId());
        Integer memberTotalCount = 0;
        Integer memberAvailableCount = 0;
        Integer memberFreezeCount = 0;
        Integer newCount = 0;
        if(memberList!=null && memberList.size() >0){
            memberTotalCount = memberList.size();
            for(Member member:memberList){
                if(member.getStatus() == AvailableStatus.AVAILABLE){
                    memberAvailableCount+=1;
                    Date begin = CalendarUtil.stringToDate(beginDate,CalendarUtil.SDF_DEFAULT_FULL);
                    Date end = CalendarUtil.stringToDate(endDate,CalendarUtil.SDF_DEFAULT_FULL);
                    if(member.getCreateAt().before(end) && begin.before(member.getCreateAt())){
                        newCount+=1;
                    }
                }else{
                    memberFreezeCount+=1;
                }
            }
        }
        BigDecimal  mTotalCount =new BigDecimal(memberTotalCount);
        BigDecimal activePre = mTotalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:activeCount.multiply(new BigDecimal("100")).divide(mTotalCount,2,RoundingMode.HALF_UP);
        orders.put("activePre",activePre);
        orders.put("memberNewCount",newCount);   //新增会员人数
        orders.put("memberTotalCount",memberTotalCount);  //所有会员人数
        orders.put("memberAvailableCount",memberAvailableCount);  //有效会员人数
        orders.put("memberFreezeCount",memberFreezeCount);  //未续费会员人数
        //前台写法统一
        orders.put("totalAmount",totalAmount);   //所有会员订单金额
        orders.put("newTotalAmount",newTotalAmount);   //新会员订单金额
        orders.put("oldTotalAmount",oldTotalAmount);    //老会员订单金额
        orders.put("totalCount",orders.get("totalCount"));       //所有会员订单数
        orders.put("oldTotalCount",orders.get("oldTotalCount"));  //老会员订单数
        orders.put("newTotalCount",orders.get("newTotalCount"));   //新会员订单数
        //客单价
        // 总金额 / 总订单数
        BigDecimal totalPrice = totalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:totalAmount.divide(totalCount,2,RoundingMode.HALF_UP);
        //新会员消费金额  / 新会员订单数
        BigDecimal newPrice = newTotalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:newTotalAmount.divide(newTotalCount,2,RoundingMode.HALF_UP);
        //老会员消费金额  / 老会员订单数
        BigDecimal oldPrice = oldTotalCount.compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:oldTotalAmount.divide(oldTotalCount,2,RoundingMode.HALF_UP);
        orders.put("totalPrice",totalPrice);   //总客单价
        orders.put("newPrice",newPrice);       //新会员客单价
        orders.put("oldPrice",oldPrice);       //老会员客单价
        return orders;
    }

    @Override
    public List<Map<String, Object>> findMemberRankingStat(String beginDate, String endDate) {
        Company company = getCurrentCompany();
        List<Map<String, Object>> consumeList =  orderDao.findMemberRankingStat(company.getId(),AvailableStatus.AVAILABLE,beginDate,endDate);
        if(consumeList.size() < 5){
            int len = 5-consumeList.size();
            for(int i=0;i<len;i++){
                Map<String, Object> map = new HashMap<>();
                map.put("amount","--");
                map.put("name","--");
                map.put("phone","--");
                consumeList.add(map);
            }
        }
        return consumeList;
    }

    @Override
    public List<Map<String, Object>> findPeriodMemberStat(String type, String cycle, String beginDate, String endDate) {
        Company company = getCurrentCompany();
        return orderDao.findPeriodMemberStat(company.getId(),cycle,beginDate,endDate);
    }

  @Override
  public Map<String, Object> findOrderStat(Long companyId, String startDate, String endDate) {
       Map<String, Object> result = new HashMap<>();
        List<Order> orderList = orderDao.findOrderList( companyId, startDate, endDate);
        BigDecimal amount = BigDecimal.ZERO;   //百货订单金额
        BigDecimal waterAmount = BigDecimal.ZERO;  //水金额
        BigDecimal amountTotal = BigDecimal.ZERO;   //销售总金额
        Integer countTotal = 0;   //订单总数
        if(orderList!=null && orderList.size() >0){
            countTotal = orderList.size();
            for(Order order:orderList){
                List<OrderItem> itemList = order.getOrderItem();
                if(itemList!=null && itemList.size()>0){
                    for(OrderItem item:order.getOrderItem()){
                        amountTotal = amountTotal.add(item.getAmount());
                        if("DEPOSIT".equals(item.getMode())){
                            waterAmount = waterAmount.add(item.getAmount());
                        }else{
                            amount = amount.add(item.getAmount());
                        }
                    }
                }
            }
        }
        result.put("amount",amount);
        result.put("waterAmount",waterAmount);
        result.put("amountTotal",amountTotal);
        result.put("countTotal",countTotal);
        return result;
  }
    @Override
    public Map<String, Object> findMemberOrder(String beginDate, String endDate) {
        Company company = getCurrentCompany();
        Map<String,Object> result = new HashMap<>();
        List<BigDecimal> amountList = orderDao.findMemberOrder(company.getId(),beginDate,endDate);
        List<String> legendList = new ArrayList<>();
        List<Map<String,Object>> countList = new ArrayList<>();
        BigDecimal five =new BigDecimal("5");
        if(amountList.size() > 0){
            BigDecimal maxAmount = amountList.get(0);
            BigDecimal len = maxAmount.divide(five,0,RoundingMode.HALF_DOWN);
            if(len.compareTo(new BigDecimal("5"))<=0){     //不超过25元
                len = five;
            }else{    //超过25元
                len = len.divide(five,0,RoundingMode.HALF_DOWN).add(BigDecimal.ONE).multiply(five);
                if(maxAmount.divide(len,0,RoundingMode.HALF_DOWN).compareTo(new BigDecimal("4")) < 0){
                    len = len.subtract(five);
                }
            }
            BigDecimal first = len;
            BigDecimal second = len.multiply(new BigDecimal("2"));
            BigDecimal third = len.multiply(new BigDecimal("3"));
            BigDecimal fourth = len.multiply(new BigDecimal("4"));
            BigDecimal fifth = len.multiply(new BigDecimal("5"));
            BigDecimal sixth = len.multiply(new BigDecimal("6"));
            legendList.add(0,("0-"+first+"元"));
            legendList.add(1,(first.add(BigDecimal.ONE))+"-"+second+"元");
            legendList.add(2,(second.add(BigDecimal.ONE))+"-"+third+"元");
            legendList.add(3,(third.add(BigDecimal.ONE))+"-"+fourth+"元");
            legendList.add(4,(fourth.add(BigDecimal.ONE))+"-"+fifth+"元");
            legendList.add(5,(fifth.add(BigDecimal.ONE))+"-"+sixth+"元");
            int  aa = 0,bb= 0,cc= 0,dd= 0,ee= 0,ff = 0;
            for(BigDecimal amount:amountList){
                if(amount.compareTo(first)<=0){
                    aa++;
                }else if(amount.compareTo(len)>0 && amount.compareTo(second)<=0){
                    bb++;
                }else if(amount.compareTo(second)>0 && amount.compareTo(third)<=0){
                    cc++;
                }else if(amount.compareTo(third)>0 && amount.compareTo(fourth)<=0){
                    dd++;
                }else if(amount.compareTo(fourth)>0 && amount.compareTo(fifth)<=0){
                    ee++;
                }else{
                    ff++;
                }
            }

            Map<String,Object> map1 = new HashMap<>();
            map1.put("value",aa);
            map1.put("name",legendList.get(0));
            countList.add(0,map1);

            if(maxAmount.compareTo(first)> 0){
                Map<String,Object> map2 = new HashMap<>();
                map2.put("value",bb);
                map2.put("name",legendList.get(1));
                countList.add(1,map2);
            }
            if(maxAmount.compareTo(second)> 0){
                Map<String,Object> map3 = new HashMap<>();
                map3.put("value",cc);
                map3.put("name",legendList.get(2));
                countList.add(2,map3);
            }
            if(maxAmount.compareTo(third)> 0){
                Map<String,Object> map4 = new HashMap<>();
                map4.put("value",dd);
                map4.put("name",legendList.get(3));
                countList.add(3,map4);
            }
            if(maxAmount.compareTo(fourth)> 0){
                Map<String,Object> map5 = new HashMap<>();
                map5.put("value",ee);
                map5.put("name",legendList.get(4));
                countList.add(4,map5);
            }
            if(maxAmount.compareTo(fifth)> 0){
                Map<String,Object> map6 = new HashMap<>();
                map6.put("value",ff);
                map6.put("name",legendList.get(5));
                countList.add(5,map6);
            }
        }
        result.put("seriesData",countList);
        result.put("legendData",legendList);
        return result;
    }
}
